package com.ruoyi.assemble.common.utils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 幂函数
 *
 * @author ZWQ
 */
public class LineFunction {
    private static final String POINT_DIGIT = "#.0000";

    /**
     * 最小二乘法，拟合y=kx+b
     *
     * @author ZWQ
     */
    public Map<String, Double> linearFunction(List<List<Double>> data) {
        Map<String, Double> result = new HashMap<>();
        Double xSum = 0.00;
        Double ySum = 0.00;
        Double xySum = 0.00;
        Double x2Sum = 0.00;
        Double k = 0.00;
        Double b = 0.00;
        int n = data.size();
        DecimalFormat df = new DecimalFormat(POINT_DIGIT);
        for (int i = 0; i < n; i++) {
            xSum = xSum + data.get(i).get(0);
            ySum = ySum + data.get(i).get(1);
            x2Sum = x2Sum + data.get(i).get(0) * data.get(i).get(0);
            xySum = xySum + data.get(i).get(0) * data.get(i).get(1);
        }
        if((x2Sum - xSum * xSum / n) == 0){
            k = 0.0;
            b = ySum / n;
        }else {
            k = (xySum - ySum * xSum / n) / (x2Sum - xSum * xSum / n);
            b = (ySum - k * xSum) / n;
        }
        result.put("a", Double.parseDouble(df.format(k)));
        result.put("b", Double.parseDouble(df.format(b)));
        return result;
    }

    /**
     * 最小二乘法，拟合y=kx+b
     *
     * @author ZWQ
     */
    public Map<String, Double> linearFunctionWithoutDis(List<List<Double>> data, Double b) {
        Map<String, Double> result = new HashMap<>();
        Double xSum = 0.00;
        Double xySum = 0.00;
        Double x2Sum = 0.00;
        Double k = 0.00;
        int n = data.size();
        DecimalFormat df = new DecimalFormat(POINT_DIGIT);
        for (int i = 0; i < n; i++) {
            xSum = xSum + data.get(i).get(0);
            x2Sum = x2Sum + data.get(i).get(0) * data.get(i).get(0);
            xySum = xySum + data.get(i).get(0) * data.get(i).get(1);
        }
        k = (xySum - b * xSum) / x2Sum;
        result.put("a", Double.parseDouble(df.format(k)));
        result.put("b", Double.parseDouble(df.format(b)));
        return result;
    }

    /**
     * 获取预测结果
     *
     * @author ZWQ
     */
    public List<List<Double>> getLinearData(Double a, Double b, List<List<Double>> realData) {
        List<List<Double>> predictData = new ArrayList<>(realData.size());
        DecimalFormat df = new DecimalFormat(POINT_DIGIT);
        for (List<Double> data : realData) {
            List<Double> result = new ArrayList<>(2);
            result.add(data.get(0));
            Double y = Double.parseDouble(df.format(a * data.get(0) + b));
            result.add(y);
            predictData.add(result);
        }
        return predictData;
    }
}
